HAPI FHIR
HAPI FHIR is the open-source Java implementation of HL7 FHIR. It is the most widely used FHIR toolkit, and for many teams "standing up a FHIR server" means deploying the HAPI JPA server.
It is really three things: a client library, a server framework, and a validation/terminology toolkit.
The client
Typed access to any FHIR server:
FhirContext ctx = FhirContext.forR4();
IGenericClient client = ctx.newRestfulGenericClient("https://example.org/fhir");
Bundle results = client.search()
.forResource(Patient.class)
.where(Patient.FAMILY.matches().value("Devkota"))
.returnBundle(Bundle.class)
.execute();
A FhirContext is expensive to create and thread-safe to reuse — create one per
FHIR version, at startup, and keep it.
The JPA server
A complete FHIR server persisted to a relational database (PostgreSQL is the usual production choice). It provides:
- Full CRUD, history and versioning
- Standard and custom search parameters
- Transaction and batch bundles
- Profile validation
- Terminology services, including loading external code systems
- Subscriptions
- Interceptor hooks for authorisation, auditing and business rules
It ships as a deployable application (hapi-fhir-jpaserver-starter) and as
libraries to embed in your own Spring application when you need control over
security and workflow.
Validation
Validation is where HAPI earns its place: resources can be checked against the base specification, against implementation-guide profiles, and against terminology bindings.
FhirValidator validator = ctx.newValidator();
validator.registerValidatorModule(new FhirInstanceValidator(ctx));
ValidationResult result = validator.validateWithResult(patient);
Validating at the boundary — rejecting bad data on write — is far cheaper than discovering malformed resources during analysis months later.
Operational notes
- Database sizing and indexing dominate performance. Search parameter indexes grow quickly; index only the parameters you actually search on.
- Turn off unused search parameters to reduce write cost.
- Authorisation is yours to implement. The
AuthorizationInterceptorgives you the hooks; the policy is a design decision. A HAPI server exposed without it is an open patient database. - Version per deployment. A
FhirContexttargets one FHIR release; running two releases side by side (as in a version upgrade) means two deployments, which is exactly how a parallel upgrade environment is built. - Cache terminology expansions; naive
$expandcalls against large value sets are slow.
Related
- FHIR servers — the wider landscape and how to choose
- HL7 FHIR — the standard itself
- Amakomaya FHIR platform
References
- HAPI FHIR — https://hapifhir.io/
- JPA server starter — https://github.com/hapifhir/hapi-fhir-jpaserver-starter